package com.wsd.common;

import com.wsd.domain.Loan;
import com.wsd.domain.RepayPlan;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * @author Wan Yucan
 * @date 2020/7/17-9:17
 */
@Component
public class LoanCalculation {
    /**
     *等额本金还款法
     * @param loan 贷款类
     * @return  还款计划列表
     */
    private final BigDecimal loanYearRate=new BigDecimal("0.08");
    private final BigDecimal loanMonthRate=new BigDecimal("0.00666667");
    public List<RepayPlan> equalPrincipal(Loan loan){
        if(loan==null){ return null; }
        loan.setRemainAmount(loan.getLoanAmount());
        List<RepayPlan> repayPlans =new LinkedList<>();
        for(int i=0;i<loan.getInstallmentNum();i++){
            RepayPlan repayPlan =new RepayPlan();
            //还款本金
            if(i!=loan.getInstallmentNum()-1) {
                repayPlan.setPrincipalPart(loan.getLoanAmount().divide(new BigDecimal(String.valueOf(loan.getInstallmentNum())), 5, BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_HALF_UP));
                loan.setRemainAmount(loan.getRemainAmount().subtract(repayPlan.getPrincipalPart()));
            }else{
                repayPlan.setPrincipalPart(loan.getRemainAmount());
            }
            //应还利息
            repayPlan.setInterestPart(loan.getLoanAmount().subtract(repayPlan.getPrincipalPart().multiply(new BigDecimal(String.valueOf(i)))).multiply(loanMonthRate).setScale(2,BigDecimal.ROUND_HALF_UP));
            //本期应还总额
            repayPlan.setRepayableAmount(repayPlan.getPrincipalPart().add(repayPlan.getInterestPart()).setScale(2,BigDecimal.ROUND_HALF_UP));
            //还款时间
            repayPlan.setRepaymentDate(loan.getLoanDate().toLocalDate().plusMonths(i+1));
            //存入还款计划列表
            repayPlan.setInstallmentIdx(i+1);
            repayPlans.add(repayPlan);
        }
        return repayPlans;
    }
    /**
     *等额本息还款法
     * @param loan 贷款类
     * @return  还款计划列表
     */
    public List<RepayPlan> equalPrincipalAndInterest(Loan loan){
        if(loan==null){ return null; }
        List<RepayPlan> repayPlans =new LinkedList<>();
        //每月等额本息还款金额
        BigDecimal loanAmount=loan.getLoanAmount().multiply(loanMonthRate).multiply(loanMonthRate.
                add(new BigDecimal("1")).pow(loan.getInstallmentNum())).divide(loanMonthRate.add(new BigDecimal("1")).
                pow(loan.getInstallmentNum()).subtract(new BigDecimal("1")),5,BigDecimal.ROUND_HALF_UP).setScale(2,BigDecimal.ROUND_HALF_UP);
        //临时记录剩余未还款
        loan.setRemainAmount(loan.getLoanAmount());
        for(int i=1;i<=loan.getInstallmentNum();i++){
            RepayPlan repayPlan =new RepayPlan();
            //应还总额
            repayPlan.setRepayableAmount(loanAmount);
            //应还利息
            repayPlan.setInterestPart(loan.getRemainAmount().multiply(loanMonthRate).setScale(2,BigDecimal.ROUND_HALF_UP));
            //应还本金
            if(i!=loan.getInstallmentNum()) {
                repayPlan.setPrincipalPart(repayPlan.getRepayableAmount().subtract(repayPlan.getInterestPart()).setScale(2, BigDecimal.ROUND_HALF_UP));
                loan.setRemainAmount(loan.getRemainAmount().subtract(repayPlan.getPrincipalPart()));
            }else {
                repayPlan.setPrincipalPart(loan.getRemainAmount());
            }
            //剩余应还本金

            //还款日期
            repayPlan.setRepaymentDate(loan.getLoanDate().toLocalDate().plusMonths(i));
            //当前还款期数
            repayPlan.setInstallmentIdx(i);
            //插入列表
            repayPlans.add(repayPlan);
        }
        return repayPlans;
    }
    /**
     *先息后本还款法
     * @param loan 贷款类
     * @return  还款计划列表
     */
    public List<RepayPlan> interesrBeforePrincipal(Loan loan){
        if(loan==null){ return null; }
        List<RepayPlan> repayPlans =new ArrayList<>();
        for(int i=1;i<=loan.getInstallmentNum();i++){
            RepayPlan repayPlan =new RepayPlan();
            //最后一期前，仅还利息，最后一期还本金+利息，
            if(i!=loan.getInstallmentNum()){
                repayPlan.setRepayableAmount(loan.getLoanAmount().multiply(loanMonthRate).setScale(2,BigDecimal.ROUND_HALF_UP));
                repayPlan.setPrincipalPart(new BigDecimal("0"));
            }else {
                repayPlan.setRepayableAmount(loan.getLoanAmount().add(loan.getLoanAmount().multiply(loanMonthRate)).setScale(2,BigDecimal.ROUND_HALF_UP));
                repayPlan.setPrincipalPart(loan.getLoanAmount().setScale(2,BigDecimal.ROUND_HALF_UP));
            }
            repayPlan.setInterestPart(loan.getLoanAmount().multiply(loanMonthRate).setScale(2,BigDecimal.ROUND_HALF_UP));
            repayPlan.setRepaymentDate(loan.getLoanDate().toLocalDate().plusMonths(i));
            repayPlan.setInstallmentIdx(i);
            repayPlans.add(repayPlan);
        }
        return repayPlans;
    }
    /**
     * 计算通过还款计划，计算总利息数据和还款总额；
     * @param repayPlans
     * @return
     */
    public RepayPlan countRepayPlan(List<RepayPlan> repayPlans){
        RepayPlan repayPlan =new RepayPlan();
        repayPlan.setInterestPart(new BigDecimal("0"));
        repayPlan.setRepayableAmount(new BigDecimal("0"));
        repayPlan.setPrincipalPart(new BigDecimal("0"));
        for(RepayPlan i: repayPlans){
            repayPlan.setInterestPart(repayPlan.getInterestPart().add(i.getInterestPart()));
            repayPlan.setRepayableAmount(repayPlan.getRepayableAmount().add(i.getRepayableAmount()));
            repayPlan.setPrincipalPart(repayPlan.getPrincipalPart().add(i.getPrincipalPart()));
        }
        return repayPlan;
    }
}
